package com.wxcms.ctrl;

import java.io.Closeable;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.RandomAccessFile;
import java.io.UnsupportedEncodingException;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.his.domain.PicSource;
import com.his.service.PicSourceService;
import com.wxcms.domain.DepEquipments;
import com.wxcms.domain.SystemAccount;
import com.wxcms.mapper.EquipmentDao;
import com.wxcms.mapper.WxCpUserDao;
import com.wxcms.service.EquipmentService;
import com.wxcms.service.SystemAccountService;

import net.coobird.thumbnailator.Thumbnails;

@Controller
@RequestMapping("/equip")
public class EquipCtrl {
	// Constants
	// ----------------------------------------------------------------------------------

	private static final int DEFAULT_BUFFER_SIZE = 20480; // ..bytes = 20KB.
	private static final long DEFAULT_EXPIRE_TIME = 604800000L; // ..ms = 1
																// week.
	private static final String MULTIPART_BOUNDARY = "MULTIPART_BYTERANGES";
	@Autowired
	private EquipmentService EQService;
	@Autowired
	private SystemAccountService SAService;

	@Autowired
	private PicSourceService PICService;

	@Autowired
	private WxCpUserDao wxUserDao;

	@Autowired
	private EquipmentDao equipdao;

	@RequestMapping(value = "/syscounts")
	public ModelAndView syscounts(HttpServletRequest request) {

		ModelAndView modelAndView = new ModelAndView("equip/syscounts");
		Object obj = request.getSession().getAttribute("userid");
		String userid = "";
		if (obj != null)
			userid = obj.toString();

		List<SystemAccount> accounts = new ArrayList<SystemAccount>();
		// 获取当前用户的职位信息
		Object position = request.getSession().getAttribute("position");
		// 判断是否管理组职位
		if ((position != null) && (position.toString().contains("admin"))) {
			accounts = SAService.getAccounts(userid);
		} else {
			accounts = SAService.getAccountsByUserid(userid);

		}
		modelAndView.addObject("accounts", accounts);

		// List<Equipment> equipments = EQService.getEquipments("");
		// modelAndView.addObject("equipments", equipments);

		return modelAndView;
	}

/**
 * 设置图片 或视频的注释信息 addPdesc
 * */
	@RequestMapping(value = "/setpdesc")
	public @ResponseBody  JSONObject setPdesc(HttpServletRequest request,
			@RequestParam(value = "puid", required = true, defaultValue = "0") String puid,
			@RequestParam(value = "fname", required = true, defaultValue = "0") String fname,
			@RequestParam(value = "pdesc", required = true, defaultValue = "0") String pdesc) {
		JSONObject obj = new JSONObject();
		
		try {
			String uname =  (String)request.getSession().getAttribute("uname"); 
			// 获取时间戳 用于标示 二维码的唯一性
			Timestamp d = new Timestamp(System.currentTimeMillis());
		/*	PicSource pic=new PicSource();
			pic.setName(uname+"("+d.toLocaleString()+"):"+fname);
			pic.setPuid(puid);
			pic.setPdesc(pdesc);
			PICService.addPdesc(pic);*/
			 PICService.addPdesc(uname+"("+d.toLocaleString()+"):"+pdesc+"\n", puid, fname);
			obj.put("success", true);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			obj.put("success", false);
		}

		return obj;

	}
	
	/**
	 * 读取设备状态
	 * 
	 */
	@RequestMapping(value = "/eqpstatus")
	public @ResponseBody  JSONArray getEQPStatus(HttpServletRequest request) {
		JSONArray arr = new JSONArray();
		List<DepEquipments> elist = EQService.getStatus();
		int len = elist.size();
		for (int i = 0; i < len; i++) {
			DepEquipments dep = elist.get(i);
			Map<String, String> map = new HashMap<String, String>();
			map.put("st", dep.getOnlinestatus());
			map.put("id", dep.getPuinfoIndex());
			arr.add(map);
		}

		return arr;

	}

	/**
	 * 获取所有视频用户 如果是 微拍管理组 depid 包含2 的 成员 （depid 是数组 查询的时候还有问题未解决）
	 * ，可以查看所有视频成员和设备资源 ，否则根据配置查看 根据职位来确定资源的查看情况
	 */

	@RequestMapping(value = "/videouser")
	public ModelAndView videouser(HttpServletRequest request) {
		// 清除 扫码状态
		request.removeAttribute("getcodeOk");

		ModelAndView modelAndView = new ModelAndView("equip/videouser");
		Object obj = request.getSession().getAttribute("userid");
		String userid = "";
		if (obj != null)
			userid = request.getSession().getAttribute("userid").toString();

		List<SystemAccount> accounts = new ArrayList<SystemAccount>();
		// 获取当前用户的职位信息
		Object position = request.getSession().getAttribute("position");
		// 判断是否管理组职位
		if ((position != null) && (position.toString().contains("admin"))) {
			accounts = SAService.getAccounts(userid);
		} else {
			accounts = SAService.getAccountsByUserid(userid);

		}
		modelAndView.addObject("accounts", accounts);

		return modelAndView;
	}

	@RequestMapping(value = "/geteqps") // 部门id
	public ModelAndView equipments(HttpServletRequest request ) {

		ModelAndView modelAndView = new ModelAndView("admin/eqpfull");
	 

		List<DepEquipments> equipments = EQService.getEquipments( );
		modelAndView.addObject("equipments", equipments);
	 
		return modelAndView;
	}
	@RequestMapping(value = "/geteqplist") // 部门id
	public ModelAndView equiplist(HttpServletRequest request ) {

		ModelAndView modelAndView = new ModelAndView("equip/equipments");
	 

		List<DepEquipments> equipments = EQService.getEquipments( );
		modelAndView.addObject("equipments", equipments);
	 
		return modelAndView;
	}
	

	@RequestMapping(value = "/imglist/{quid}")
	public ModelAndView imgList(@PathVariable String quid,
			@RequestParam(value = "isPage", required = false, defaultValue = "0") long isPage,
			@RequestParam(value = "time", required = false, defaultValue = "0") long time) {
		if (isPage == 1) {

			return new ModelAndView("redirect:/mindex?quid=" + quid);
		}

		ModelAndView modelAndView = new ModelAndView("equip/imglist");

		List<PicSource> pics = PICService.getPics("PICTURE", quid, time, 10);
		modelAndView.addObject("pics", pics);

		return modelAndView;
	}

	@RequestMapping(value = "/videolist/{quid}")
	public ModelAndView videoList(@PathVariable String quid,
			@RequestParam(value = "isPage", required = false, defaultValue = "0") long isPage,
			@RequestParam(value = "time", required = false, defaultValue = "0") long time) {
		
		if (isPage == 1) {
			return new ModelAndView("redirect:/mindex?quid=" + quid);
		}

		ModelAndView modelAndView = new ModelAndView("equip/videolist");

		List<PicSource> pics = PICService.getPics("REALTIME", quid, time, 10);
		modelAndView.addObject("videos", pics);

		return modelAndView;
	}

	@RequestMapping(value = "/imgView")
	public ModelAndView imageView(HttpServletRequest request,
			@RequestParam(value = "urls", defaultValue = "") List<String> urls,
			@RequestParam(value = "puid", defaultValue = "") String puid,
			@RequestParam(value = "index", defaultValue = "0") String index) throws UnsupportedEncodingException {

		ModelAndView modelAndView = new ModelAndView("mobile/bigImageView");
		// String _name= new
		// String(request.getParameter("name").getBytes("ISO8859-1"), "UTF-8");
		// String _name=new String(name.getBytes("ISO8859-1"), "UTF-8");
		String _name = equipdao.getEquipName(puid);
		modelAndView.addObject("urls", urls);
		modelAndView.addObject("title", _name);
		modelAndView.addObject("index", index);
		System.out.println("===================================\n" + urls);
		System.out.println("===================================\n" + _name);
		return modelAndView;
	}

	@RequestMapping(value = "/videoView")
	public ModelAndView videoView(HttpServletRequest request,
			@RequestParam(value = "url", defaultValue = "") String url,
			@RequestParam(value = "puid", defaultValue = "") String puid) {

		ModelAndView modelAndView = new ModelAndView("mobile/videoView");

		modelAndView.addObject("url", url);
		 
		modelAndView.addObject("title", equipdao.getEquipName(puid));
		return modelAndView;
	}

	// /picsrc/${row.path!}/${row.name!}/151038400596510844/00/20160509/
	// 20160509151946_000D.jpg
	@RequestMapping(value = "/picsrc/{img}")

	public   void picsrc(HttpServletRequest request, HttpServletResponse response, @PathVariable String img,
			@RequestParam(value = "isBig", required = false, defaultValue = "0") long isBig) {

		if (StringUtils.isEmpty(img)) {
			img = "";
		}

		String fileName =   img.replace("-", "\\") + ".jpg";
		File file = new File(fileName);

		// 判断文件是否存在如果不存在就返回默认图标
		if (!(file.exists() && file.canRead())) {
			file = new File(request.getSession().getServletContext().getRealPath("/") + "res/images/ddkj_huidu_no.png");
		}

		FileInputStream inputStream;
		
		OutputStream stream = null ;
		byte[] data;
		try {
			response.setContentType("image/jpeg");

			  stream = response.getOutputStream();
			if (isBig == 1)// 默认都是发送小图
			{
				inputStream = new FileInputStream(file);
			    data = new byte[(int) file.length()];
				int length = inputStream.read(data);
				inputStream.close();
				inputStream=null;
				
				stream.write(data);
				
				data=null;
				
			} else {

				Thumbnails.of(file.getPath()).size(400, 400).toOutputStream(stream);
			}
 
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally{
			try {
				stream.flush();
				stream.close();
			} catch (Exception e2) {
				// TODO: handle exception
			}
			data=null;
			stream=null;
			file=null;
			System.gc();
		}
		
		
	}

	// 缩略图
	@RequestMapping(value = "/video/{ifile}")
	public   void picsrc_thumb(HttpServletRequest request, HttpServletResponse response,
			@PathVariable String ifile) throws IOException {

		String fileName1 =   ifile.replace("-", "\\") + ".mp4";
		File file = new File(fileName1);

		if (file == null || !file.exists()) {
			response.sendError(HttpServletResponse.SC_NOT_FOUND);
			return;
		}

		String contentType = null;// (String) objectMap.get("contentType");

		String fileName = file.getName();
		long length = file.length();
		long lastModified = file.lastModified();
		String eTag = fileName + "_" + length + "_" + lastModified;
		long expires = System.currentTimeMillis() + DEFAULT_EXPIRE_TIME;

		// Validate request headers for caching
		// ---------------------------------------------------

		// If-None-Match header should contain "*" or ETag. If so, then return
		// 304.
		String ifNoneMatch = request.getHeader("If-None-Match");
		if (ifNoneMatch != null && matches(ifNoneMatch, fileName)) {
			response.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
			response.setHeader("ETag", eTag); // Required in 304.
			response.setDateHeader("Expires", expires); // Postpone cache with 1
			file=null;											// week.
			return;
		}

		// If-Modified-Since header should be greater than LastModified. If so,
		// then return 304.
		// This header is ignored if any If-None-Match header is specified.
		long ifModifiedSince = request.getDateHeader("If-Modified-Since");
		if (ifNoneMatch == null && ifModifiedSince != -1 && ifModifiedSince + 1000 > lastModified) {
			response.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
			response.setHeader("ETag", eTag); // Required in 304.
			response.setDateHeader("Expires", expires); // Postpone cache with 1
			file=null;												// week.
			return;
		}

		// Validate request headers for resume
		// ----------------------------------------------------

		// If-Match header should contain "*" or ETag. If not, then return 412.
		String ifMatch = request.getHeader("If-Match");
		if (ifMatch != null && !matches(ifMatch, fileName)) {
			response.sendError(HttpServletResponse.SC_PRECONDITION_FAILED);
			file=null;	
			return;
		}

		// If-Unmodified-Since header should be greater than LastModified. If
		// not, then return 412.
		long ifUnmodifiedSince = request.getDateHeader("If-Unmodified-Since");
		if (ifUnmodifiedSince != -1 && ifUnmodifiedSince + 1000 <= lastModified) {
			response.sendError(HttpServletResponse.SC_PRECONDITION_FAILED);
			file=null;	
			return;
		}

		// Validate and process range
		// -------------------------------------------------------------

		// Prepare some variables. The full Range represents the complete file.
		Range full = new Range(0, length - 1, length);
		List<Range> ranges = new ArrayList<Range>();

		// Validate and process Range and If-Range headers.
		String range = request.getHeader("Range");
		if (range != null) {

			// Range header should match format "bytes=n-n,n-n,n-n...". If not,
			// then return 416.
			if (!range.matches("^bytes=\\d*-\\d*(,\\d*-\\d*)*$")) {
				response.setHeader("Content-Range", "bytes */" + length); // Required
																			// in
																			// 416.
				response.sendError(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE);
				file=null;	
				return;
			}

			String ifRange = request.getHeader("If-Range");
			if (ifRange != null && !ifRange.equals(eTag)) {
				try {
					long ifRangeTime = request.getDateHeader("If-Range"); // Throws
																			// IAE
																			// if
																			// invalid.
					if (ifRangeTime != -1 && ifRangeTime + 1000 < lastModified) {
						ranges.add(full);
					}
				} catch (IllegalArgumentException ignore) {
					ranges.add(full);
				}
			}

			// If any valid If-Range header, then process each part of byte
			// range.
			if (ranges.isEmpty()) {
				for (String part : range.substring(6).split(",")) {
					// Assuming a file with length of 100, the following
					// examples returns bytes at:
					// 50-80 (50 to 80), 40- (40 to length=100), -20
					// (length-20=80 to length=100).
					long start = sublong(part, 0, part.indexOf("-"));
					long end = sublong(part, part.indexOf("-") + 1, part.length());

					if (start == -1) {
						start = length - end;
						end = length - 1;
					} else if (end == -1 || end > length - 1) {
						end = length - 1;
					}

					// Check if Range is syntactically valid. If not, then
					// return 416.
					if (start > end) {
						response.setHeader("Content-Range", "bytes */" + length); // Required
																					// in
																					// 416.
						response.sendError(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE);
						file=null;	
						return;
					}

					// Add range.
					ranges.add(new Range(start, end, length));
				}
			}
		}

		// Prepare and initialize response
		// --------------------------------------------------------

		// Get content type by file name and set content disposition.
		String disposition = "inline";

		// If content type is unknown, then set the default value.
		// For all content types, see:
		// http://www.w3schools.com/media/media_mimeref.asp
		// To add new content types, add new mime-mapping entry in web.xml.
		if (contentType == null) {
			contentType = "application/octet-stream";
		} else if (!contentType.startsWith("image")) {
			// Else, expect for images, determine content disposition. If
			// content type is supported by
			// the browser, then set to inline, else attachment which will pop a
			// 'save as' dialogue.
			String accept = request.getHeader("Accept");
			disposition = accept != null && accepts(accept, contentType) ? "inline" : "attachment";
		}

		// Initialize response.
		response.reset();
		response.setBufferSize(DEFAULT_BUFFER_SIZE);
		response.setHeader("Content-Disposition", disposition + ";filename=\"" + fileName + "\"");
		response.setHeader("Accept-Ranges", "bytes");
		response.setHeader("ETag", eTag);
		response.setDateHeader("Last-Modified", lastModified);
		response.setDateHeader("Expires", expires);

		// Send requested file (part(s)) to client
		// ------------------------------------------------

		// Prepare streams.
		RandomAccessFile input = null;
		OutputStream output = null;

		try {
			// Open streams.
			input = new RandomAccessFile(file, "r");
			output = response.getOutputStream();

			if (ranges.isEmpty() || ranges.get(0) == full) {

				// Return full file.
				Range r = full;
				response.setContentType(contentType);
				response.setHeader("Content-Range", "bytes " + r.start + "-" + r.end + "/" + r.total);
				response.setHeader("Content-Length", String.valueOf(r.length));

				copy(input, output, r.start, r.length);

			} else if (ranges.size() == 1) {

				// Return single part of file.
				Range r = ranges.get(0);
				response.setContentType(contentType);
				response.setHeader("Content-Range", "bytes " + r.start + "-" + r.end + "/" + r.total);
				response.setHeader("Content-Length", String.valueOf(r.length));
				response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT); // 206.

				// Copy single part range.
				copy(input, output, r.start, r.length);

			} else {

				// Return multiple parts of file.
				response.setContentType("multipart/byteranges; boundary=" + MULTIPART_BOUNDARY);
				response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT); // 206.

				// Cast back to ServletOutputStream to get the easy println
				// methods.
				ServletOutputStream sos = (ServletOutputStream) output;

				// Copy multi part range.
				for (Range r : ranges) {
					// Add multipart boundary and header fields for every range.
					sos.println();
					sos.println("--" + MULTIPART_BOUNDARY);
					sos.println("Content-Type: " + contentType);
					sos.println("Content-Range: bytes " + r.start + "-" + r.end + "/" + r.total);

					// Copy single part range of multi part range.
					copy(input, output, r.start, r.length);
				}

				// End with multipart boundary.
				sos.println();
				sos.println("--" + MULTIPART_BOUNDARY + "--");
			}
		} finally {
			close(output);
			close(input);
			output=null;
			input=null;
			file=null;	
		
		}

		// // 取头参数
		// String range = request.getHeader("range");
		// String browser = request.getHeader("User-Agent");
		// if (browser.indexOf("Firefox") != -1) {
		// // 火狐浏览器
		// byte[] data = getBytesFromFile(new File("C:/media/final.ogg"));
		// response.setContentType("video/ogg");
		// response.setContentLength(data.length);
		// response.setHeader("Content-Range", range +
		// Integer.valueOf(data.length - 1));
		// response.setHeader("Accept-Ranges", "bytes");
		// response.setHeader("Etag", "W/\"9767057-1323779115364\"");
		//
		// byte[] content = new byte[1024];
		// BufferedInputStream is = new BufferedInputStream(new
		// ByteArrayInputStream(data));
		// OutputStream os = response.getOutputStream();
		// while (is.read(content) != -1) {
		// os.write(content);
		// }
		// is.close();
		// os.close();
		// } else if (browser.indexOf("MSIE") != -1) {
		// // IE9以上浏览器
		// byte[] data = getBytesFromFile(file);
		// String diskfilename = "final.mp4";
		// response.setContentType("video/mpeg");
		// // response.setContentType("application/octet-stream");
		// response.setHeader("Content-Disposition", "attachment; filename=\"" +
		// diskfilename + "\"");
		// response.setContentLength(data.length);
		// response.setHeader("Content-Range", range +
		// Integer.valueOf(data.length - 1));
		// response.setHeader("Accept-Ranges", "text/x-dvi");
		// response.setHeader("Etag", "W/\"9767057-1323779115364\"");
		// byte[] content = new byte[1024];
		// BufferedInputStream is = new BufferedInputStream(new
		// ByteArrayInputStream(data));
		// OutputStream os = response.getOutputStream();
		// while (is.read(content) != -1) {
		// os.write(content);
		// }
		// is.close();
		// os.close();
		// } else if (browser.indexOf("Chrome") != -1) {
		// // 谷歌浏览器
		// byte[] data = getBytesFromFile(file);
		// String diskfilename = "final.mp4";
		// response.setContentType("video/mp4");
		// // response.setContentType("application/octet-stream");
		// response.setHeader("Content-Disposition", "attachment; filename=\"" +
		// diskfilename + "\"");
		// System.out.println("data.length " + data.length);
		// response.setContentLength(data.length);
		// response.setHeader("Content-Range", range +
		// Integer.valueOf(data.length - 1));
		// response.setHeader("Accept-Ranges", "bytes");
		// response.setHeader("Etag", "W/\"9767057-1323779115364\"");
		// byte[] content = new byte[1024];
		// BufferedInputStream is = new BufferedInputStream(new
		// ByteArrayInputStream(data));
		// OutputStream os = response.getOutputStream();
		// while (is.read(content) != -1) {
		// os.write(content);
		// }
		// is.close();
		// os.close();
		// } else if (browser.indexOf("CoreMedia") != -1) {
		// // 其他浏览器
		// byte[] data = getBytesFromFile(file);
		// String diskfilename = "final.mp4";
		// response.setContentType("video/mpeg");
		// response.setHeader("Content-Disposition", "attachment; filename=\"" +
		// diskfilename + "\"");
		// byte[] content = new byte[1024];
		// BufferedInputStream is = new BufferedInputStream(new
		// ByteArrayInputStream(data));
		// OutputStream os = response.getOutputStream();
		// while (is.read(content) != -1) {
		// os.write(content);
		// }
		// is.close();
		// os.close();
		// }
		//

	}

	// Helpers (can be refactored to public utility class)
	// ----------------------------------------

	private void close(Closeable resource) {
		if (resource != null) {
			try {
				resource.close();
			} catch (IOException ignore) {
			}
		}
	}

	private void copy(RandomAccessFile input, OutputStream output, long start, long length) throws IOException {
		byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];
		int read;

		try {
			if (input.length() == length) {
				// Write full range.
				while ((read = input.read(buffer)) > 0) {
					output.write(buffer, 0, read);
				}
			} else {
				input.seek(start);
				long toRead = length;

				while ((read = input.read(buffer)) > 0) {
					if ((toRead -= read) > 0) {
						output.write(buffer, 0, read);
					} else {
						output.write(buffer, 0, (int) toRead + read);
						break;
					}
				}
			}
		} catch (IOException ignore) {
		}
	}

	private long sublong(String value, int beginIndex, int endIndex) {
		String substring = value.substring(beginIndex, endIndex);
		return (substring.length() > 0) ? Long.parseLong(substring) : -1;
	}

	private boolean accepts(String acceptHeader, String toAccept) {
		String[] acceptValues = acceptHeader.split("\\s*(,|;)\\s*");
		Arrays.sort(acceptValues);
		return Arrays.binarySearch(acceptValues, toAccept) > -1
				|| Arrays.binarySearch(acceptValues, toAccept.replaceAll("/.*$", "/*")) > -1
				|| Arrays.binarySearch(acceptValues, "*/*") > -1;
	}

	private boolean matches(String matchHeader, String toMatch) {
		String[] matchValues = matchHeader.split("\\s*,\\s*");
		Arrays.sort(matchValues);
		return Arrays.binarySearch(matchValues, toMatch) > -1 || Arrays.binarySearch(matchValues, "*") > -1;
	}

	// Inner classes
	// ------------------------------------------------------------------------------

	protected class Range {
		long start;
		long end;
		long length;
		long total;

		public Range(long start, long end, long total) {
			this.start = start;
			this.end = end;
			this.length = end - start + 1;
			this.total = total;
		}
	}

	/**
	 * 读取文件字节
	 * 
	 * @param file
	 * @return
	 * @throws IOException
	 */
	private static byte[] getBytesFromFile(File file) throws IOException {
		InputStream is = new FileInputStream(file);
		long length = file.length();
		if (length > Integer.MAX_VALUE) {
			return null;
		}
		byte[] bytes = new byte[(int) length];
		int offset = 0;
		int numRead = 0;
		while ((offset < bytes.length) && ((numRead = is.read(bytes, offset, bytes.length - offset)) >= 0)) {
			offset += numRead;
		}
		if (offset < bytes.length) {
			throw new IOException("Could not completely read file " + file.getName());
		}
		is.close();
		return bytes;
	}

}
